home *** CD-ROM | disk | FTP | other *** search
- /* File "socket.cpp", Light Sockets - Copyright (C) Matt Slot, 1996 */
- /* Foundation layer for the Light Sockets networking abstraction routines. */
-
- #include <stdio.h>
- #include <stdlib.h>
- #include <string.h>
- #include <time.h>
-
- #include "stddebug.h"
- #include "stdtypes.h"
-
- #include "datagram.h"
- #include "netstack.h"
- #include "platform.h"
- #include "socket.h"
-
- /* **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** */
- /* **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** */
-
- Socket::Socket() {
- SocketResult &error = instError;
-
- error = eSocketNoError;
-
- inited = false;
- bound = false;
- stack = 0;
-
- #ifdef _DEBUG
- logEnabled = false;
- logBuffers[0] = 0;
- logBuffers[1] = 0;
- #endif
- }
-
- /* **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** */
- /* **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** */
-
- Socket::~Socket() {
- Socket::Dispose();
- }
-
- /* **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** */
- /* **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** */
- #pragma mark -
-
- SocketResult Socket::Create(SocketType socketType) {
- SocketResult &error = instError;
-
- /* Parameter validation */
- qThrowIfError(error, 0);
-
- /* Structure initialization */
- this->socketType = socketType;
- spinProc = SpinStub;
- spinRefcon = 0;
-
- /* Locate, instantiate, and initialize the network stack */
- qThrowIfError(SelectNetworkStack(this, stack), 0);
- qThrowIfNull(stack, eSocketErrInternal, kSocketErrInternalStr);
- qThrowIfError(stack->DoLoad(), 0);
- qThrowIfError(stack->DoCreate(), 0);
-
- #ifdef _DEBUG
- qThrowIfNull(logBuffers[0] = new char[kSocketLoggingSize], eSocketErrOutOfMem,
- kSocketErrBadParamStr);
- qThrowIfNull(logBuffers[1] = new char[kSocketLoggingSize], eSocketErrOutOfMem,
- kSocketErrBadParamStr);
- #endif
-
- /* CATCH */
- qCatch();
-
- if (error)
- Dispose();
-
- return(error);
- }
-
- /* **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** */
- /* **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** */
-
- SocketResult Socket::Tickle() {
- SocketResult &error = instError;
-
- /* Parameter validation */
- qThrowIfError(error, 0);
- qAssertIfNull(stack, eSocketErrInternal, kSocketErrInternalStr);
-
- qThrowIfError(stack->DoTickle(), 0);
- qThrowIfError(CallSpinProc(), 0);
-
- /* CATCH */
- qCatch();
-
- return(error);
- }
-
- /* **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** */
- /* **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** */
-
- SocketResult Socket::Dispose() {
- SocketResult &error = instError;
-
- if (stack) {
- qTraceIfError(stack->DoDispose(), 0);
- qTraceIfError(stack->DoUnload(), 0);
- delete stack;
- stack = 0;
- }
-
- #ifdef _DEBUG
- if (IsLogging()) DisableLogging();
- if (curLogBuffer && *curLogBuffer) CallSpinProc();
- if (logBuffers[0]) delete logBuffers[0];
- if (logBuffers[1]) delete logBuffers[1];
- #endif
-
- /* CATCH */
- qCatch();
-
- return(error);
- }
-
- /* **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** */
- /* **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** */
- #pragma mark -
-
- SocketResult Socket::Bind(SocketAddressPtr reqAddress,
- SocketAddressPtr retAddress) {
- SocketResult &error = instError;
-
- /* Parameter validation */
- qThrowIfError(error, 0);
- qAssertIfNull(stack, eSocketErrInternal, kSocketErrInternalStr);
-
- qThrowIfError(stack->DoBind(reqAddress, retAddress), 0);
-
- /* CATCH */
- qCatch();
-
- return(error);
- }
-
- /* **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** */
- /* **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** */
-
- SocketResult Socket::Unbind() {
- SocketResult &error = instError;
-
- /* Parameter validation */
- qThrowIfError(error, 0);
- qAssertIfNull(stack, eSocketErrInternal, 0);
-
- qThrowIfError(stack->DoUnbind(), 0);
-
- /* CATCH */
- qCatch();
-
- return(error);
- }
-
-
- /* **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** */
- /* **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** */
- #pragma mark -
-
- SocketResult Socket::GetInstError() {
- return(this->instError);
- }
-
- /* **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** */
- /* **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** */
-
- void Socket::ResetInstError() {
- this->instError = eSocketNoError;
- }
-
- /* **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** */
- /* **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** */
-
- SocketType Socket::GetSocketType() {
- return(this->socketType);
- }
-
- /* **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** */
- /* **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** */
-
- Bool8 Socket::IsSocketInited() {
- return(this->inited);
- }
-
- /* **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** */
- /* **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** */
-
- void Socket::SetSocketInited(Bool8 inited) {
- this->inited = inited;
- }
-
- /* **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** */
- /* **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** */
-
- Bool8 Socket::IsSocketBound(SocketAddressPtr boundTo) {
- if (this->bound && boundTo)
- *boundTo = this->boundTo;
- return(this->bound);
- }
-
- /* **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** */
- /* **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** */
-
- void Socket::SetSocketBound(Bool8 bound, SocketAddress &boundTo) {
- if (this->bound = bound)
- this->boundTo = boundTo;
- }
-
- /* **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** */
- /* **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** */
- #pragma mark -
-
- SocketResult Socket::GetSpinProc(SocketSpinProc &proc, void * &refcon) {
- SocketResult &error = instError;
-
- /* Parameter validation */
- qThrowIfError(error, 0);
-
- proc = spinProc;
- refcon = spinRefcon;
-
- /* CATCH */
- qCatch();
-
- return(error);
- }
-
- /* **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** */
- /* **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** */
-
- SocketResult Socket::SetSpinProc(SocketSpinProc proc, void *refcon) {
- SocketResult &error = instError;
-
- /* Parameter validation */
- qThrowIfError(error, 0);
-
- spinProc = (proc) ? proc : SpinStub;
- spinRefcon = (proc) ? refcon : 0;
-
- /* CATCH */
- qCatch();
-
- return(error);
- }
-
- /* **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** */
- /* **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** */
-
- SocketResult Socket::CallSpinProc() {
- SocketResult error = eSocketNoError;
-
- /* Parameter validation */
- qThrowIfError(error, 0);
- qAssertIfNull(spinProc, eSocketErrInternal, kSocketErrInternalStr);
-
- /* Make the function call */
- qThrowIfError((*spinProc)(this, spinRefcon), 0);
-
- /* CATCH */
- qCatch();
-
- return(error);
- }
-
- /* **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** */
- /* **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** */
-
- SocketResult Socket::SpinStub(SocketRef socket, void *refcon) {
- SocketResult error = eSocketNoError;
-
- /* Parameter validation */
- qThrowIfError(error, 0);
- qAssertIfNull(socket, eSocketErrInternal, kSocketErrInternalStr);
-
- #if defined(PLATFORM_MAC)
- SystemTask();
- #endif
-
- /* CATCH */
- qCatch();
-
- return(error);
- }
-
- /* **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** */
- /* **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** */
- #pragma mark -
-
- #ifdef _DEBUG
-
- SocketResult Socket::EnableLogging(char *filename, Bool8 replacing) {
- SocketResult &error = instError;
-
- /* Parameter validation */
- qThrowIfError(error, 0);
- qThrowIfNull(filename, eSocketErrBadParam, kSocketErrBadParamStr);
- qThrowIfFalse(strlen(filename) < sizeof(logName),
- eSocketErrBadParam, kSocketErrBadParamStr);
-
- strcpy(logName, filename);
- curLogBuffer = logBuffers[0];
- *(logBuffers[0]) = 0;
- *(logBuffers[1]) = 0;
-
- qThrowIfError(GetSpinProc(logSpinProc, logSpinRefcon), 0);
- qThrowIfError(SetSpinProc(LoggingSpinStub, 0), 0);
- switch(qGetSocketTransfer(GetSocketType())) {
- case eSocketTransferDatagram:
- qThrowIfError(((DatagramSocketRef) this)->GetWriteProc(
- (DatagramWriteProc *) &logWriteProc, &logWriteRefcon), 0);
- qThrowIfError(((DatagramSocketRef) this)->SetWriteProc(
- (DatagramWriteProc) LoggingDatagramWriteStub, 0), 0);
- qThrowIfError(((DatagramSocketRef) this)->GetReadProc(
- (DatagramReadProc *) &logReadProc, &logReadRefcon), 0);
- qThrowIfError(((DatagramSocketRef) this)->SetReadProc(
- (DatagramReadProc) LoggingDatagramReadStub, 0), 0);
- break;
-
- case eSocketTransferStream:
- qThrowErr(eSocketErrNoSupport, kSocketErrNoSupportStr);
- break;
-
- case eSocketTransferXaction:
- qThrowErr(eSocketErrNoSupport, kSocketErrNoSupportStr);
- break;
-
- default:
- qThrowErr(eSocketErrInternal, kSocketErrInternalStr);
- break;
- }
-
- logEnabled = true;
- logInited = false;
- logReplace = replacing;
-
- /* CATCH */
- qCatch();
-
- return(error);
- }
-
- /* **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** */
- /* **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** */
-
- SocketResult Socket::DisableLogging() {
- SocketResult &error = instError;
-
- logEnabled = false;
- logInited = true;
- logReplace = false;
-
- /* CATCH */
- qCatch();
-
- return(error);
- }
-
- /* **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** */
- /* **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** */
-
- Bool8 Socket::IsLogging() {
- return(logEnabled);
- }
-
- /* **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** */
- /* **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** */
-
- SocketResult Socket::LoggingSpinStub(SocketRef socket, void *refcon) {
- SocketResult error = eSocketNoError;
- SInt32 result;
- Char8 *logCopy = 0;
- FILE *logFile = 0;
-
- /* Parameter validation */
- qThrowIfError(error, 0);
- qAssertIfNull(socket, eSocketErrInternal, kSocketErrInternalStr);
- qThrowIfNull(socket->logSpinProc, eSocketErrInternal,
- kSocketErrInternalStr);
- qThrowIfFalse(strlen(socket->logName), eSocketErrBadParam,
- kSocketErrBadParamStr);
-
- if (*socket->curLogBuffer) {
-
- /* We maintain two buffers because interrupt-based networking continues
- to accumulate packets and fill the log through the fprintf(), which
- can be a "Bad Thing(tm)". Swapping the active buffer helps this. */
-
- if (socket->curLogBuffer == socket->logBuffers[0]) {
- socket->curLogBuffer = socket->logBuffers[1];
- logCopy = socket->logBuffers[0];
- }
- else {
- socket->curLogBuffer = socket->logBuffers[0];
- logCopy = socket->logBuffers[1];
- }
-
- logCopy[kSocketLoggingSize-1] = 0;
-
- if (socket->logReplace) {
- qThrowIfNull(logFile = fopen(socket->logName, "w"),
- eSocketErrOutOfMem, "Error opening logfile");
- socket->logReplace = false;
- }
- else {
- qThrowIfNull(logFile = fopen(socket->logName, "a"),
- eSocketErrOutOfMem, "Error opening logfile");
-
- if (!socket->logInited) {
- result = fprintf(logFile, "\n");
- qThrowIfTrue(result < 0, result, "Error writing logfile");
- }
- }
-
- if (!socket->logInited) {
- socket->logInited = true;
- result = fprintf(logFile,
- "Binary dated: " __DATE__ ", " __TIME__ "\n");
- qThrowIfTrue(result < 0, result, "Error writing logfile");
-
- result = fprintf(logFile, "\n");
- qThrowIfTrue(result < 0, result, "Error writing logfile");
- }
-
- result = fprintf(logFile, "%s", logCopy);
- qThrowIfTrue(result < 0, result, "Error writing logfile");
- }
-
- qThrowIfError((*socket->logSpinProc)(socket, socket->logSpinRefcon), 0);
-
- /* CATCH */
- qCatch();
-
- if (logCopy) *logCopy = 0;
- if (logFile) qTraceIfError(fclose(logFile), "Error closing logfile");
-
- return(error);
- }
-
- /* **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** */
- /* **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** */
-
- SocketResult Socket::LoggingDatagramReadStub(Socket *socket, void *refcon,
- Byte8 *dataPtr, UInt32 dataLen, SocketAddressPtr address) {
- SocketResult error = eSocketNoError;
- char *logCopy = 0;
-
- /* Parameter validation */
- qThrowIfError(error, 0);
- qAssertIfNull(socket, eSocketErrInternal, kSocketErrInternalStr);
- qThrowIfNull(socket->curLogBuffer, eSocketErrInternal, kSocketErrInternalStr);
- qThrowIfNull(socket->logReadProc, eSocketErrInternal, kSocketErrInternalStr);
-
- if (socket->logEnabled) {
- UInt32 dataDone;
- Char8 hex[ARBITRARY_BUFFER_SIZE];
- Char8 ascii[ARBITRARY_BUFFER_SIZE];
-
- /* Draw the packet information */
- socket->LoggingConvertBytes((Byte8 *)socket, sizeof(socket), hex, 0, 0);
- strcat(socket->curLogBuffer, hex);
- strcat(socket->curLogBuffer, "- DGM RECV - ");
- for(dataDone = 0; dataDone < address->length; dataDone += 16) {
- socket->LoggingConvertBytes(address->buffer.bytes + dataDone,
- address->length - dataDone, 0, hex, 0);
- strcat(socket->curLogBuffer, hex);
- }
- strcat(socket->curLogBuffer, "\n");
-
- /* Draw the packet data */
- for(dataDone = 0; dataDone < dataLen; dataDone += 16) {
- socket->LoggingConvertBytes(dataPtr + dataDone,
- dataLen - dataDone, 0, hex, ascii);
- strcat(socket->curLogBuffer, "\t\t | ");
- strcat(socket->curLogBuffer, hex);
- strcat(socket->curLogBuffer, "| ");
- strcat(socket->curLogBuffer, ascii);
- strcat(socket->curLogBuffer, "\n");
- }
- }
-
- qThrowIfError((*socket->logReadProc)((DatagramSocketRef) socket,
- socket->logReadRefcon, dataPtr, dataLen, address), 0);
-
- /* CATCH */
- qCatch();
-
- return(error);
- }
-
- /* **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** */
- /* **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** */
-
- SocketResult Socket::LoggingDatagramWriteStub(Socket *socket, void *refcon,
- Byte8 *dataPtr, UInt32 dataLen, SocketAddressPtr address) {
- SocketResult error = eSocketNoError;
- char *logCopy = 0;
-
- /* Parameter validation */
- qThrowIfError(error, 0);
- qAssertIfNull(socket, eSocketErrInternal, kSocketErrInternalStr);
- qThrowIfNull(socket->curLogBuffer, eSocketErrInternal, kSocketErrInternalStr);
- qThrowIfNull(socket->logWriteProc, eSocketErrInternal,
- kSocketErrInternalStr);
-
- if (socket->logEnabled) {
- UInt32 dataDone;
- Char8 hex[ARBITRARY_BUFFER_SIZE];
- Char8 ascii[ARBITRARY_BUFFER_SIZE];
-
- /* Draw the packet information */
- socket->LoggingConvertBytes((Byte8 *)socket, sizeof(socket), hex, 0, 0);
- strcat(socket->curLogBuffer, hex);
- strcat(socket->curLogBuffer, "- DGM SEND - ");
- for(dataDone = 0; dataDone < address->length; dataDone += 16) {
- socket->LoggingConvertBytes(address->buffer.bytes + dataDone,
- address->length - dataDone, 0, hex, 0);
- strcat(socket->curLogBuffer, hex);
- }
- strcat(socket->curLogBuffer, "\n");
-
- /* Draw the packet data */
- for(dataDone = 0; dataDone < dataLen; dataDone += 16) {
- socket->LoggingConvertBytes(dataPtr + dataDone,
- dataLen - dataDone, 0, hex, ascii);
- strcat(socket->curLogBuffer, "\t\t | ");
- strcat(socket->curLogBuffer, hex);
- strcat(socket->curLogBuffer, "| ");
- strcat(socket->curLogBuffer, ascii);
- strcat(socket->curLogBuffer, "\n");
- }
- }
-
- qThrowIfError((*socket->logWriteProc)((DatagramSocketRef) socket,
- socket->logReadRefcon, dataPtr, dataLen, address), 0);
-
- /* CATCH */
- qCatch();
-
- return(error);
- }
-
- /* **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** */
- /* **** **** **** **** **** **** **** **** **** **** **** **** **** **** **** */
-
- void Socket::LoggingConvertBytes(Byte8 *dataPtr, UInt32 dataLen,
- Char8 *addr, Char8 *hex, Char8 *ascii) {
- UInt32 i, j, val;
- Char8 *hexDigits = "0123456789ABCDEF";
-
- if (addr) {
- for(i=(UInt32) dataPtr, j=0; j<8; i<<=4)
- addr[j++] = hexDigits[i>>28];
- addr[j++] = ' ';
- addr[j++] = 0;
- }
-
- if (hex) {
- for(i=j=0; i<16; i++) {
- hex[j++] = (i>=dataLen) ? ':' : hexDigits[(UInt8) dataPtr[i]>>4];
- hex[j++] = (i>=dataLen) ? ':' : hexDigits[(UInt8) dataPtr[i]&0x0F];
- if ((j+1)%9 == 0) hex[j++] = ' ';
- }
- hex[j++] = 0;
- }
-
- if (ascii) {
- for(i=j=0; i<16; i++)
- ascii[j++] = (i>=dataLen) ? ':' :
- ((dataPtr[i]<0x20)||(dataPtr[i]>0x7E)) ? '*' : dataPtr[i];
- ascii[j++] = 0;
- }
- }
-
- #endif /* _DEBUG */
-
-